package com.szwistar.common.comm.blocktrans;

import com.szwistar.common.comm.StreamFrameAnalyzer;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;

/**
 * 块传输协议编解码
 */
class BlockTransFrameDecoder extends StreamFrameAnalyzer implements ProtocolDecoder {
	protected static Logger LOG = LoggerFactory.getLogger("Default");

	public BlockTransFrameDecoder() {
		super(BlockTransFrame.SYNC, BlockTransFrame.MAX_FRAME_LEN, BlockTransFrame.MIN_FRAME_LEN, 0);
	}

	@Override
	protected int judgeFrameLength(IoSession session, IoBuffer in) {
		return (4 + in.getInt(0));
	}

	@Override
	protected void decodeFrame(IoSession session, IoBuffer in, ProtocolDecoderOutput out) {
		try {
			BlockTransFrame frame = BlockTransFrame.createByDecode(in);
			out.write(frame.payload);
		} catch (Exception e) {
			LOG.error("BlockTransFrame 数据帧解码失败！\r\n{}", e.getMessage());
		}
	}

	@Override
	public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) {
		// 逐个字节处理
		while(in.hasRemaining()) {
			feed(session, in.get(), out);
		}
	}

	@Override
	public void finishDecode(IoSession session, ProtocolDecoderOutput out) {
	}

	@Override
	public void dispose(IoSession session) {
		super.dispose();
	}
}

class BlockTransFrameEncoder implements ProtocolEncoder {
	@Override
	public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
		// 调用帧的编码函数编码
		IoBuffer buf = new BlockTransFrame((BlockTransPayload) message).encode();
		if(buf != null) {
			buf.flip();
			out.write(buf);
			buf.free();
		}
	}

	@Override
	public void dispose(IoSession session) {
	}
}

class BlockTransPayloadRegistry extends HashMap<Integer, Class<? extends BlockTransPayload>> {
	private static final long serialVersionUID = -5948763919003653068L;
}

public class BlockTransFrameCodec  {
	// 净荷类型注册表
	private static final BlockTransPayloadRegistry payloadTypeRegistry = new BlockTransPayloadRegistry();

	/**
	 * 注册传输的净荷类型
	 * ！！！注意：未注册的净荷类型无法进行解码！！！
	 */
	public static final void registerPayloadType(int typeId, Class<? extends BlockTransPayload> typeClazz) {
		payloadTypeRegistry.put(typeId, typeClazz);
	}

	public static final Class<? extends BlockTransPayload> getPayloadTypeById(int typeId) {
		return payloadTypeRegistry.get(typeId);
	}

	public static ProtocolCodecFilter newFilter() {
		BlockTransFrameDecoder decoder = new BlockTransFrameDecoder();
		BlockTransFrameEncoder encoder = new BlockTransFrameEncoder();
		ProtocolCodecFilter filter = new ProtocolCodecFilter(encoder, decoder);
		decoder.setFilter(filter);
		return filter;
	}
}
